package com.zkl.evaluation.scoring;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zkl.evaluation.model.dto.question.QuestionContentDTO;
import com.zkl.evaluation.model.entity.App;
import com.zkl.evaluation.model.entity.Question;
import com.zkl.evaluation.model.entity.ScoringResult;
import com.zkl.evaluation.model.entity.UserAnswer;
import com.zkl.evaluation.model.vo.QuestionVO;
import com.zkl.evaluation.service.QuestionInformationService;
import com.zkl.evaluation.service.QuestionService;
import com.zkl.evaluation.service.ScoringResultService;

import javax.annotation.Resource;
import java.util.List;
import java.util.Optional;

/**
 * 自定义打分类应用评分策略
 *
 */
@ScoringStrategyConfig(appType = 0, scoringStrategy = 0)
public class CustomScoreScoringStrategy implements ScoringStrategy {

    @Resource
    private QuestionService questionService;

    @Resource
    private ScoringResultService scoringResultService;

    @Resource
    private QuestionInformationService questionInformationService;

    @Override
    public UserAnswer doScore(List<String> choices, App app) throws Exception {
        Long appId = app.getId();
        // 1. 根据 id 查询到题目和题目结果信息（按分数降序排序）
        Question question = questionService.getOne(
                Wrappers.lambdaQuery(Question.class).eq(Question::getAppId, appId)
        );
        List<ScoringResult> scoringResultList = scoringResultService.list(
                Wrappers.lambdaQuery(ScoringResult.class)
                        .eq(ScoringResult::getAppId, appId)
                        .orderByDesc(ScoringResult::getResultScoreRange)
        );

        // 2. 统计用户的总得分
        int totalScore = 0;
        QuestionVO questionVO = QuestionVO.objToVo(question);
        List<QuestionContentDTO> questionContent = questionVO.getQuestionContent();

        String type = questionInformationService.getQuestionTypeByAppId(appId);

        // 遍历题目列表
        for (int i = 0; i < questionContent.size(); i++) {
            QuestionContentDTO questionContentDTO = questionContent.get(i);
            String answer = choices.get(i);

            //不同题型
            if ("single".equals(type) || "multi".equals(type)) {
                // 处理单选题和多选题
                totalScore += calculateChoiceScore(questionContentDTO, answer);
            } else if ("fill".equals(type) || "subjective".equals(type)) {
                // 处理填空题和简答题
                totalScore += calculateTextAnswerScore(questionContentDTO, answer);
            }
        }

        // 3. 遍历得分结果，找到第一个用户分数大于得分范围的结果，作为最终结果
        ScoringResult maxScoringResult = scoringResultList.get(0);
        for (ScoringResult scoringResult : scoringResultList) {
            if (totalScore >= scoringResult.getResultScoreRange()) {
                maxScoringResult = scoringResult;
                break;
            }
        }

        // 4. 构造返回值，填充答案对象的属性
        UserAnswer userAnswer = new UserAnswer();
        userAnswer.setAppId(appId);
        userAnswer.setAppType(app.getAppType());
        userAnswer.setScoringStrategy(app.getScoringStrategy());
        userAnswer.setChoices(JSONUtil.toJsonStr(choices));
        userAnswer.setResultId(maxScoringResult.getId());
        userAnswer.setResultName(maxScoringResult.getResultName());
        userAnswer.setResultDesc(maxScoringResult.getResultDesc());
        userAnswer.setResultPicture(maxScoringResult.getResultPicture());
        userAnswer.setResultScore(totalScore);
        return userAnswer;
    }

    /**
     * 计算单选题和多选题的得分
     *
     * @param questionContentDTO 题目内容
     * @param answer 用户选择的答案
     * @return 得分
     */
    private int calculateChoiceScore(QuestionContentDTO questionContentDTO, String answer) {
        int score = 0;
        for (QuestionContentDTO.Option option : questionContentDTO.getOptions()) {
            if (option.getKey().equals(answer)) {
                score = option.getScore();
                break;
            }
        }
        return score;
    }

    /**
     * 计算填空题和简答题的得分
     *
     * @param questionContentDTO 题目内容
     * @param answer 用户输入的答案
     * @return 得分
     */
    private int calculateTextAnswerScore(QuestionContentDTO questionContentDTO, String answer) {
        int score = 0;
        for (QuestionContentDTO.Answer refAnswer : questionContentDTO.getAnswers()) {
            // 简单比较答案和参考答案
            if (answer.contains(refAnswer.getValue())) {
                score += refAnswer.getScore();
            }
        }
        return score;
    }
}
